package syf.stack;

public class StackCalKuoHao {
    public static void main(String[] args) {
        //计算的表达式
        String expression="(1+2+3+4)*6+2";
        //两个栈 :数栈和符号栈
        MyCalculator numStack=new MyCalculator(10);
        MyCalculator signStack=new MyCalculator(10);
        char out;
        int num1;
        int num2;
        int opr;
        int index=0;
        int res;
        String NumAdd="";
        int pri;
        int peakTop;
        boolean flag=true;
        while (true){
            //将里面的数字或符号转化为单个字符
            out=expression.substring(index,index+1).charAt(0);
            if (signStack.isSign(out)){//判断为符号
                pri=signStack.priority(out);
                if (pri==3)
                    flag=false;
                if(signStack.isEmpty())//如果为空直接入栈
                    signStack.push(out);
                else{//不为空 判断顶栈的符号和这个符号的优先级，如果里面的比这个小，则直接存入，否则弹出运算
                    peakTop=signStack.priority(signStack.peakTop());
                    if(pri<=peakTop){//当前的优先级小于等于顶部的，弹出顶部的进行运算
                        //右括号
                        if (peakTop!=3&&peakTop!=4){//(2*5+2*5)*6+2
                            num1 = numStack.pop();
                            num2 = numStack.pop();
                            opr = signStack.pop();
                            res = numStack.Cal(num1, num2, opr);
                            numStack.push(res);
                            if (signStack.isEmpty()&&index==expression.length()-1)
                                break;
                        }
                        if (peakTop==4) {
                            signStack.pop();
                            while (true) {
                                if (numStack.GetSize()==0){
                                    signStack.pop();
                                    signStack.push(out);
                                    break;
                                }
                                num1 = numStack.pop();
                                num2 = numStack.pop();
                                opr = signStack.pop();
                                res = numStack.Cal(num1, num2, opr);
                                numStack.push(res);
                                //将左括号取出
                                if (signStack.priority(signStack.peakTop())==3) {
                                    signStack.pop();
                                    signStack.push(out);
                                    flag=true;
                                    break;
                                }
                            }
                        }
                        else {
                            signStack.push(out);
                        }
                    }
                    else{//当前优先级大于顶部直接入栈
                        if (pri==4){
                            num1 = numStack.pop();
                            num2 = numStack.pop();
                            opr = signStack.pop();
                            res = numStack.Cal(num1, num2, opr);
                            numStack.push(res);
                        }
                        signStack.push(out);
                    }
                }
            }
            else{//判断不是符号   因为可能出现两位数和多位数
//                numStack.push(out-'0');
                NumAdd+=out;
                //查看后一位
                //如果为最后一位则直接入栈
                if (index==expression.length()-1)
                    numStack.push(Integer.parseInt(NumAdd));
                else {
                    //如果下一位为符号则直接入栈，否则继续判断
                    if (signStack.isSign(expression.substring(index + 1, index + 2).charAt(0))) {
                        numStack.push(Integer.parseInt(NumAdd));
                        NumAdd = "";
                    }
                }
            }
            index++;
            if (index>=expression.length())
                break;
        }
        //判断是否运算结束
        while (true){
            if (signStack.isEmpty())
                break;
            num1=numStack.pop();
            num2=numStack.pop();
            opr=signStack.pop();
            res=numStack.Cal(num1,num2,opr);
            numStack.push(res);
        }
        System.out.println(numStack.pop());
    }
}
class MyCalculator {
    private int top=-1;//初始为-1
    private final int MaxSize;//栈的大小
    private final int[] stack;//数组模拟栈
    //创建栈
    public MyCalculator(int MaxSize){
        this.MaxSize=MaxSize;
        stack=new int[MaxSize];
    }
    //判断是否为空
    public boolean isEmpty(){
        return top==-1;
    }
    //判断是否为满
    public boolean isFull(){
        return top==MaxSize-1;
    }
    //入栈
    public void push(int value){
        if (isFull()){
            System.out.println("栈满了");
            return;}
        stack[++top]=value;
    }
    //出栈
    public int pop(){
        if (isEmpty())
            throw new RuntimeException("栈已经空了");
        return stack[top--];
    }
    //size
    public int GetSize(){
        return top;
    }
    //遍历栈
    public void show(){
        if (isEmpty()){
            return;}
        for (int i=top;i>=0;i--){
            System.out.println("栈元素为"+stack[i]);
        }
    }
    //查看栈顶的符号
    public int peakTop(){
        return stack[top];
    }
    //返回运算符优先级 只考虑加减乘除
    public int priority(int num){
        if (')'==num)
            return 4;
        //让左括号始终在符号栈里面不影响其他符号，直到右括号出现计算。
        else if ('('==num)
            return 3;
        else if('*'==num|'/'==num)
            return 2;
        else if ('+'==num|'-'==num)
            return 1;
        else
            return 0;
    }
    //判断是否为运算符
    public boolean isSign(char oper){
        return oper == '*' | oper == '/' | oper == '+' | oper == '-'|oper=='('|oper==')';
    }
    public int Cal(int num1, int num2, int opr){
        int result=0;
        switch (opr) {
            case '+':result=num2+num1;break;
            case '-':result=num2-num1;break;
            case '*':result=num2*num1;break;
            case '/':result=num2/num1;break;
            default:break;
        }
        return result;
    }
}
